﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Security.Permissions;
using System.Web.Script.Services;
using System.Web.Services;
using DataObject.DataAccess;
using DataObject.Database;
using DataObject.Helpers;
using DataObject.Model;

namespace OBS
{
    /// <summary>
    ///     Summary description for Update
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [ScriptService]
    public class Update : WebService
    {
        #region Constructors & destructors

        #endregion

        #region  Categories

        [WebMethod]
        public bool DeleteAgent(string AgentId)
        {
            try
            {
                AgentPricesDAO.CreateInstant().Delete(x => x.AgentID.ToLower().Equals(AgentId.ToLower()));
                GuestDAO.CreateInstant().Delete(n => n.GuestID.ToLower().Equals(AgentId.ToLower()));
                return true;
            }
            catch
            {
                return false;
            }
        }

        [WebMethod]
        public bool DeleteBoat(string BoatID)
        {
            try
            {
                CabinDAO.CreateInstant().DeleteCabin(BoatID);
                BoatDAO.CreateInstant().Delete(n => n.BoatID.ToLower().Equals(BoatID.ToLower()));
                return true;
            }
            catch
            {
                return false;
            }
        }

        [WebMethod]
        public bool DeleteContract(string ContractID)
        {
            try
            {
                ContractDAO.CreateInstant().Delete(n => n.ContractID.ToLower().Equals(ContractID.ToLower()));
                return true;
            }
            catch
            {
                return false;
            }
        }

        [WebMethod]
        public bool DeleteCabin(int CabinID)
        {
            try
            {
                CabinDAO.CreateInstant().Delete(n => n.CabinID == CabinID);
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region Services

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool InsertService(ServiceDTO serviceEntity)
        {
            serviceEntity.ModifiedBy = User.Identity.Name;
            return ServiceDAO.CreateInstant().Insert(serviceEntity);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateService(ServiceDTO serviceEntity)
        {
            serviceEntity.ModifiedBy = User.Identity.Name;
            return ServiceDAO.CreateInstant().Update(serviceEntity);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool DeleteService(Guid serviceID)
        {
            return ServiceDAO.CreateInstant().Delete(serviceID);
        }

        #endregion

        #region Providers

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool InsertProvider(ProviderDTO providerEntity)
        {
            providerEntity.Active = true;
            providerEntity.ModifiedBy = User.Identity.Name;
            return ProviderDAO.CreateInstant().Insert(providerEntity);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateProvider(ProviderDTO providerEntity)
        {
            providerEntity.ModifiedBy = User.Identity.Name;
            return ProviderDAO.CreateInstant().Update(providerEntity);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool DeleteProvider(Guid providerID)
        {
            try
            {
                return ProviderDAO.CreateInstant().DeleteProvider(providerID);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region Routes

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool InsertRoute(RouteDTO route)
        {
            route.ModifiedBy = User.Identity.Name;
            route.Active = true;
            return RouteDAO.CreateInstant().InsertRoute(route);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateRoute(RouteDTO route)
        {
            route.ModifiedBy = User.Identity.Name;
            route.Active = true;
            if (null != route.ProviderName && route.ProviderName.Trim().Length == 0)
                route.ProviderName = null;
            return RouteDAO.CreateInstant().UpdateRoute(route);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool ChangeStateRoute(Guid routeID)
        {
            return RouteDAO.CreateInstant().ChangeState(routeID);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool DeleteRoute(Guid routeID)
        {
            try
            {
                return RouteDAO.CreateInstant().DeleteRoute(routeID);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region Reservations

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool InsertReservation(Reservation reservation, Guest guest, IList<PaymentBatch> paymentBatches)
        {
            if (reservation.Status != (int) RESERVATION_STATUS.Cancelled)
            {
                BuildCabinStatus(reservation);
            }
            else
            {
                foreach (ReservationDetail item in reservation.ReservationDetails)
                {
                    item.RDID = Helper.NewSeqGuid();
                }
            }

            // Insert payments
            foreach (ReservationPayment item in reservation.ReservationPayments)
            {
                item.ReservationPaymentID = Helper.NewSeqGuid();
            }

            reservation.ReservationID = Helper.NewSeqGuid();
            reservation.CreatedByID = User.Identity.Name;
            reservation.ModifiedByID = User.Identity.Name;
            reservation.CreationDate = DateTime.Now;
            reservation.ModifiedDate = DateTime.Now;

            return ReservationDAO.CreateInstant().CreateReservation(reservation, guest, paymentBatches);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public object InsertConfirmReservation(Reservation reservation, Guest guest, IList<PaymentBatch> paymentBatches)
        {
            bool result = false;
            result = InsertReservation(reservation, guest, paymentBatches);

            return new {Result = result, reservation.ReservationID};
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateReservation(Reservation reservation, Guest guest, IList<PaymentBatch> paymentBatches)
        {
            if (reservation.Status != (int) RESERVATION_STATUS.Cancelled)
            {
                BuildCabinStatus(reservation);
            }
            else
            {
                foreach (ReservationDetail item in reservation.ReservationDetails)
                {
                    item.RDID = Helper.NewSeqGuid();
                }
            }

            foreach (ReservationPayment item in reservation.ReservationPayments)
            {
                item.ReservationPaymentID = Helper.NewSeqGuid();
            }

            reservation.ModifiedByID = User.Identity.Name;
            reservation.ModifiedDate = DateTime.Now;

            return ReservationDAO.CreateInstant().UpdateReservation(reservation, guest, paymentBatches);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateConfirmReservation(Reservation reservation, Guest guest, IList<PaymentBatch> paymentBatches)
        {
            return UpdateReservation(reservation, guest, paymentBatches);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateBoatForReservation(Guid reservationID, string boatID, string departureDateString,
            string boardingDateString, int numOfNights, int numOfCabins)
        {
            DateTime departureDate = DateTime.Parse(departureDateString, CultureInfo.InvariantCulture);
            DateTime boardingDate = DateTime.Parse(boardingDateString, CultureInfo.InvariantCulture);
            return ReservationDAO.CreateInstant()
                .UpdateBoatForReservation(reservationID, boatID, departureDate, boardingDate, numOfNights, numOfCabins);
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool DeleteReservation(Guid reservationID)
        {
            try
            {
                return ReservationDAO.CreateInstant().DeleteReservation(reservationID);
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region Extra Service

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public ReservationExtra InsertExtraService()
        {
            var extra = new ReservationExtra
            {
                ExtraID = Helper.NewSeqGuid(),
                ExtraDate = DateTime.Today,
                Description = String.Empty
            };
            return extra;
        }

        #endregion

        #region Sticky

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool CreateSticky(string date, string description)
        {
            bool result = false;
            try
            {
                DateTime stickyDate;
                if (!DateTime.TryParse(date, CultureInfo.InvariantCulture, DateTimeStyles.None, out stickyDate))
                {
                    throw new InvalidCastException();
                }

                result = StickyDAO.CreateInstant().Create(new StickyEntity
                {
                    StickyDate = stickyDate,
                    Description = description
                });
            }
            catch (Exception)
            {
                throw;
            }
            return result;
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateSticky(string date, string description)
        {
            bool result = false;
            try
            {
                DateTime stickyDate;
                if (!DateTime.TryParse(date, CultureInfo.InvariantCulture, DateTimeStyles.None, out stickyDate))
                {
                    throw new InvalidCastException();
                }
                StickyDAO.CreateInstant().Update(new StickyEntity
                {
                    StickyDate = stickyDate,
                    Description = description
                });
                result = true;
            }
            catch (Exception)
            {
                throw;
            }
            return result;
        }

        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool DeleteSticky(string date)
        {
            bool result = false;
            try
            {
                DateTime stickyDate;
                if (!DateTime.TryParse(date, CultureInfo.InvariantCulture, DateTimeStyles.None, out stickyDate))
                {
                    throw new InvalidCastException();
                }
                StickyDAO.CreateInstant().Delete(stickyDate);
                result = true;
            }
            catch (Exception)
            {
                throw;
            }
            return result;
        }

        #endregion

        #region Location

        /// <summary>
        ///     Insert Location
        /// </summary>
        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool InsertLocation(Location locationEntity)
        {
            return LocationDAO.CreateInstant().InsertLocation(locationEntity);
        }

        /// <summary>
        ///     Update Location
        /// </summary>
        [WebMethod]
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        public bool UpdateLocation(Location locationEntity)
        {
            return LocationDAO.CreateInstant().UpdateLocation(locationEntity);
        }

        #endregion

        #region Private Methods

        private void BuildCabinStatus(Reservation reservation)
        {
            foreach (ReservationDetail detail in reservation.ReservationDetails)
            {
                detail.RDID = Helper.NewSeqGuid();

                int cabinStatus = detail.CabinStatus;

                if (cabinStatus.Equals((int) CABIN_STATUS.Release))
                {
                    // Release
                    continue;
                }

                for (int j = 0; j < reservation.NumOfNights; j++)
                {
                    var item = new CabinStatusEntity();
                    item.RDID = detail.RDID;
                    item.CabinID = detail.CabinID;
                    item.Status = detail.CabinStatus; // Correct
                    item.Date = reservation.CheckInDate.AddDays(j);

                    if (cabinStatus.Equals((int) CABIN_STATUS.Blocked))
                    {
                        // Block cabin status
                        item.BlockDates = detail.BlockDates;
                    }
                    else
                    {
                        // (int)CABIN_STATUS.Booked
                        item.BlockDates = 0;
                    }

                    detail.CabinStatusEntities.Add(item);
                }
            }
        }

        #endregion
    }
}